#pragma once
#ifndef skyADT_h__
#define skyADT_h__

#include "../inc/skyType.h"
#include "../inc/skyList.h"
#include "../inc/skyRTTI.h"
namespace Sky
{
	namespace NADT
	{

		//////////////////////////////////////////////////////////////////////////
		#define DECL_REFF_OBJ()       refObject re;                  \
		TVoid  addRef(){if(0 == re.addRef());}                       \
		TVoid  relRef(){if(0 == re.relRef())delete this;}			 \
		virtual ~xObject(){}

		template <typename cls>
		class xAutoRelPtr
		{
		private:
			void operator = (xAutoRelPtr& rref){}
			xAutoRelPtr(xAutoRelPtr& a){}
		public:
			cls* pThis;
		public:
			cls* operator ->()
			{
				return pThis;
			}
			xAutoRelPtr(cls* p):pThis(p){}
			~xAutoRelPtr(){pThis->relRef();}
		};

		template <typename cls>
		class xAutoDelPtr
		{
		private:
			void operator = (xAutoDelPtr& rref){}
			xAutoDelPtr(xAutoDelPtr& a){}
		public:
			cls* pThis;
		public:
			cls* operator ->()
			{
				return pThis;
			}
			xAutoDelPtr(cls* p):pThis(p){}
			~xAutoDelPtr(){delete pThis;}
		};
		template <typename cls>
		xAutoRelPtr<cls>  auto_release_cast(cls* p){return xAutoRelPtr<cls>(p);}
		template <typename cls>
		xAutoDelPtr<cls>  auto_delete_cast(cls* p){return xAutoDelPtr<cls>(p);}

		//////////////////////////////////////////////////////////////////////////
		template <typename cls>
		class xReferencePtr
		{
		private:
			cls* pThis;
		private:
			xReferencePtr():pThis(vNull){}
		public:
			xReferencePtr(cls* p):pThis(p){if(p)p->addRef();}
			xReferencePtr(xAutoRelPtr<cls>& p):pThis(p.pThis){pThis->addRef();}
			~xReferencePtr()
			{
				if(pThis)pThis->relRef();
			}
			void operator = (xReferencePtr& c)
			{
				if(pThis)
					pThis->relRef();
				pThis = c.pThis;
				if(pThis)
					pThis->addRef();
				return;
			}
			cls* operator ->()
			{
				return pThis;
			}
			template <typename castclass>
				xReferencePtr<castclass> cast_pointer(xReferencePtr& ptr)
			{
				return xReferencePtr<castclass>(ptr.pThis);
			}
		};

		class xTreeNode : public Object
		{
			DECL_RTTI1(xTreeNode,Object);
		public:
			xTreeNode* m_Prev;
			xTreeNode* m_Next;
			xTreeNode* m_Parent;
			xTreeNode* m_FirstChild;
			xTreeNode* m_LastChild;
		public:
			xTreeNode();
			//
			xTreeNode* getParent();
			//
			xTreeNode* getFirstChild();
			//
			xTreeNode* getLastChild();
			//
			xTreeNode* getNextSibling();
			//
			xTreeNode* getPrevSibling();
			//
			xTreeNode* getNext();
			//
			xTreeNode* getNext_InSubTree(xTreeNode* node);
			//
			xTreeNode* getPrev_InSubTree(xTreeNode* node);
			//
			xTreeNode* getPrev();
			//
			xTreeNode* getNext_OverChild();
		public:
			TBool attachFirstChild(xTreeNode* child);
			TBool attachLastChild(xTreeNode* child);
			TBool attachNextSibling(xTreeNode* sibling);
			TBool attachPrveSibling(xTreeNode* sibling);

			xTreeNode* detachFirstChild();
			xTreeNode* detachLastChild();
			xTreeNode* detachNextSibling();
			xTreeNode* detachPrevSibling();
			xTreeNode* detachCurrent();
			//deatch itself as an clone one
			xTreeNode* detachColne();
			xTreeNode* exchangeCurrent(xTreeNode* node);
			xTreeNode* detachAllChildren();
		};
	}
}
#endif // xADT_h__